
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Workflow.ComponentModel.Design;
using System.Xml;
using System.Xml.Serialization;
using OpenComposite.HumanActivity.Contracts.Participants;
using OpenComposite.EII.Designer.SCA;
using OpenComposite.EII.Forms;
using OpenComposite.EII.Repository;

namespace OpenComposite.EII.Designer.Workflow
{
	public partial class FormHumanTaskProperties : Form
	{
		#region Initialization
		public FormHumanTaskProperties(Service service)
		{
			InitializeComponent();

			_service = service;
			_logact = null;

			showProperties();
		}
		public FormHumanTaskProperties(LogicalActivity logact, Repository.Workflow workflow)
		{
			InitializeComponent();

			_service = null;
			_logact = logact;
			_workflow = workflow;

			showProperties();
		}
		#endregion

		#region Private Members

		#region Variables
		private Service _service;
		private LogicalActivity _logact;
		private Repository.Workflow _workflow;
		#endregion

		#region Methods
		private void showProperties()
		{
			if ( _service != null ) {
				txtName.Text = _service.Name;
				txtDescription.Text = _service.Description;
			} else if ( _logact != null ) {
				txtName.Text = _logact.Name;
				txtDescription.Text = _logact.Description;
				if ( _logact.ExtendedProperties != null && _logact.ExtendedProperties.HumanComponentProperties != null ) {
					txtProcessName.Text = _logact.ExtendedProperties.HumanComponentProperties.ProcessName;
					txtActivityName.Text = _logact.ExtendedProperties.HumanComponentProperties.ActivityName;
					txtSubject.Text = _logact.ExtendedProperties.HumanComponentProperties.Subject;
				} else {
					txtProcessName.Text = "";
					txtActivityName.Text = "";
					txtSubject.Text = "";
				}
				if ( string.IsNullOrEmpty(txtProcessName.Text) ) {
					txtProcessName.Text = _workflow.Name;
				}
				if ( string.IsNullOrEmpty(txtActivityName.Text) ) {
					txtActivityName.Text = _logact.DisplayName.IfNullOrEmpty(_logact.Name);
				}
				if ( string.IsNullOrEmpty(txtSubject.Text) ) {
					txtSubject.Text = "No Subject";
				}
			} else {
				throw new NullReferenceException("Missing service or logical activity.");
			}
			HumanComponentProperties props = getProperties();
			foreach ( HumanComponentParticipant part in props.Participants ) {
				switch ( part.ParticipationType ) {
					case ParticipationType.IncludedParticipant:
						lstIncludedParticipants.Items.Add(part);
						break;
					case ParticipationType.ExcludedParticipant:
						lstExcludedParticipants.Items.Add(part);
						break;
					case ParticipationType.IncludedReaderParticipant:
						break;
					case ParticipationType.ExcludedReaderParticipant:
						break;
					case ParticipationType.IncludedPastDueParticipant:
						break;
					case ParticipationType.ExcludedPastDueParticipant:
						break;
				}
			}
			txtAssemblyName.Text = props.AssemblyName;
			txtFormName.Text = props.FormName;

			showHActivityInfo();
		}
		private void saveService()
		{
			if ( _service != null ) {
				_service.Name = txtName.Text;
				_service.Description = txtDescription.Text;
			} else if ( _logact != null ) {
				_logact.Name = txtName.Text;
				_logact.Description = txtDescription.Text;
			}
			HumanComponentProperties props = new HumanComponentProperties();
			foreach ( HumanComponentParticipant part in lstIncludedParticipants.Items ) {
				part.ParticipationType = ParticipationType.IncludedParticipant;
				props.Participants.Add(part);
			}
			foreach ( HumanComponentParticipant part in lstExcludedParticipants.Items ) {
				part.ParticipationType = ParticipationType.ExcludedParticipant;
				props.Participants.Add(part);
			}
			props.ProcessName = txtProcessName.Text;
			props.ActivityName = txtActivityName.Text;
			props.Subject = txtSubject.Text;

			props.AssemblyName = txtAssemblyName.Text;
			props.FormName = txtFormName.Text;

			setProperties(props);

			initializeParameterResolve(props.Participants);

			if ( _service != null ) {
				_service.Save();
			} else if ( _logact != null ) {
				_logact.Save();
			}
		}

		private void initializeParameterResolve(List<HumanComponentParticipant> participants)
		{
			if ( _logact == null || _workflow == null ) {
				return;
			}
			WorkflowLoader loader = _workflow.GetService(typeof(WorkflowDesignerLoader)) as WorkflowLoader;
			RepositoryService repSvc = _workflow.GetService(typeof(RepositoryService)) as RepositoryService;
			MemberCreationService memberCreation = _workflow.GetService(typeof(IMemberCreationService)) as MemberCreationService;
			Debug.Assert(loader != null, "WorkflowLoader not available.");
			Debug.Assert(repSvc != null, "RepositoryService not available.");
			Debug.Assert(memberCreation != null, "MemberCreationService not available.");
			foreach ( HumanComponentParticipant part in participants ) {
				if ( part.Type == ParticipantType.ParticipantRule ) {
					if ( !loader.RuleIDs.Contains(part.ID) ) {
						loader.RuleIDs.Add(part.ID);
					}
					RepositoryBusinessRule partrule = repSvc.GetItem<RepositoryBusinessRule>(part.ID);
					if ( partrule == null || partrule.IsDeleted ) continue;

					string[] strsParams = partrule.Parameters.Split(';');
					foreach ( string sParam in strsParams ) {
						string[] p = sParam.Split(':');

						OpenComposite.EII.Repository.Workflow.RuleParameterResolve rpr =
							new OpenComposite.EII.Repository.Workflow.RuleParameterResolve();
						if ( p.Length > 0 )
							rpr.ParameterName = p[0];
						if ( p.Length > 1 )
							rpr.ParameterDataType = p[1];

						memberCreation.CreatePropertyForRuleParameterResolution(
							loader.FullClassName, rpr.ParameterName,
							OpenComposite.EII.Helpers.GetDotNetTypeOfDataTypeString(rpr.ParameterDataType),
							"");
						if ( !_workflow.ExtendedProperties.WorkflowVariables.Contains(rpr) )
							_workflow.ExtendedProperties.WorkflowVariables.Add(rpr);
					}
				}
			}
			_workflow.SetRuleIDs(loader.RuleIDs);

			#region check that all workflow variables used in rules
			List<string> lstVarNms = new List<string>();
			foreach ( RepositoryBusinessRule rule in _workflow.GetRules() ) {
				Dictionary<string, string> parameters = rule.GetParameters();
				lstVarNms.AddRange(parameters.Keys);
			}
			Repository.Workflow.RuleParameterResolve[] rprs = _workflow.ExtendedProperties.WorkflowVariables.ToArray();
			foreach ( Repository.Workflow.RuleParameterResolve rpr in rprs ) {
				if ( !lstVarNms.Contains(rpr.ParameterName) )
					_workflow.ExtendedProperties.WorkflowVariables.Remove(rpr);
			}
			#endregion
		}
		private HumanComponentProperties getProperties()
		{
			HumanComponentProperties props = null;
			if ( _service != null ) {
				props = _service.ExtendedProperties.HumanComponentProperties;
				if ( props == null ) {
					_service.ExtendedProperties.HumanComponentProperties = new HumanComponentProperties();
					props = _service.ExtendedProperties.HumanComponentProperties;
				}
			} else if ( _logact != null ) {
				props = _logact.ExtendedProperties.HumanComponentProperties;
			} else {
				props = new HumanComponentProperties();
			}
			return props;
		}
		private void setProperties(HumanComponentProperties props)
		{
			if ( _service != null && props != null &&
				 _service.ExtendedProperties.HumanComponentProperties != props ) {
				_service.ExtendedProperties.HumanComponentProperties = props;
			} else if ( _logact != null && props != null &&
				 _logact.ExtendedProperties.HumanComponentProperties != props ) {
				_logact.ExtendedProperties.HumanComponentProperties = props;
			}
		}
		private void showPartSelectForm(ListBox lstParts)
		{
			FormParticipants frm = new FormParticipants();
			Participants parts = new Participants();
			foreach ( HumanComponentParticipant part in lstParts.Items ) {
				parts.Add(part.GetIParticipant());
			}
			frm.Init(parts, _workflow.ParticipantPolicy);
			if ( frm.ShowDialog() == DialogResult.OK ) {
				lstParts.Items.Clear();
				foreach ( IParticipant part in frm.Participants ) {
					lstParts.Items.Add(new HumanComponentParticipant(part));
				}
			}
		}
		private void showHActivityInfo()
		{
			txtHAct.SuspendLayout();
			if ( _logact.HumanActivityID > 0 ) {
				Repository.HumanActivity ha = _logact.GetHumanActivity();
				if ( ha != null ) {
					txtHAct.ForeColor = SystemColors.ControlText;
					txtHAct.TextAlign = HorizontalAlignment.Left;
					txtHAct.Text = ha.Name;
					txtAssemblyName.Text = ha.FormAssemblyName;
					txtFormName.Text = ha.FormName;
					txtFormSchema.Text = ha.FormSchemaName;
				} else {
					clearHAInfos();
				}
			} else if ( _logact.LogicalMethod != null &&
						_logact.LogicalMethod.IsAssignedTo == LogicalMethodAssignedTo.HumanActivity ) {
				Repository.HumanActivity ha = _logact.LogicalMethod.GetAssignedHumanActivity();
				if ( ha != null ) {
					txtHAct.ForeColor = SystemColors.ControlText;
					txtHAct.TextAlign = HorizontalAlignment.Left;
					txtHAct.Text = ha.Name;
					txtAssemblyName.Text = ha.FormAssemblyName;
					txtFormName.Text = ha.FormName;
					txtFormSchema.Text = ha.FormSchemaName;
				} else {
					clearHAInfos();
				}
			} else if ( _service == null || _service.HumanActivity == null ) {
				clearHAInfos();
			} else {
				txtHAct.ForeColor = SystemColors.ControlText;
				txtHAct.TextAlign = HorizontalAlignment.Left;
				txtHAct.Text = _service.HumanActivity.Name;
				txtAssemblyName.Text = _service.HumanActivity.FormAssemblyName;
				txtFormName.Text = _service.HumanActivity.FormName;
				txtFormSchema.Text = _service.HumanActivity.FormSchemaName;
			}
			txtHAct.ResumeLayout(true);
		}

		private void clearHAInfos()
		{
			txtHAct.ForeColor = SystemColors.GrayText;
			txtHAct.TextAlign = HorizontalAlignment.Center;
			txtHAct.Text = "- Select A Human Activity -";
			txtAssemblyName.Text = "";
			txtFormName.Text = "";
			txtFormSchema.Text = "";
		}
		/// <summary>
		/// Get the imagelist index of participant type.
		/// </summary>
		/// <param name="participant">IParticipant object.</param>
		/// <returns>Index in imagelist.</returns>
		private int getImgIndex(ParticipantType parttype)
		{
			switch ( parttype ) {
				case ParticipantType.EmailParticipant:
					return (int)ParticipantIndex.Email;
				case ParticipantType.PropertyParticipant:
					return (int)ParticipantIndex.Property;
				case ParticipantType.Organization:
					return (int)ParticipantIndex.Org;
				case ParticipantType.OrganizationUnit:
					return (int)ParticipantIndex.OrgUnit;
				case ParticipantType.ParticipantRule:
					return (int)ParticipantIndex.ParticipantRule;
				case ParticipantType.PartnerRule:
					return -1;
				case ParticipantType.PartnerRole:
					return -1;
				case ParticipantType.Role:
					return (int)ParticipantIndex.Role;
				case ParticipantType.User:
					return (int)ParticipantIndex.User;
				case ParticipantType.ActivityUser:
					return (int)ParticipantIndex.Activity;
				default:
					return -1;
			}
		}
		#endregion

		#region Event Handlers

		private void btnSelectIncludedParticipants_Click(object sender, EventArgs e)
		{
			showPartSelectForm(lstIncludedParticipants);
		}

		private void btnSelectExcludedParticipants_Click(object sender, EventArgs e)
		{
			showPartSelectForm(lstExcludedParticipants);
		}

		private void tsbtnOK_Click(object sender, EventArgs e)
		{
			saveService();
			this.DialogResult = DialogResult.OK;
			this.Close();
		}

		private void tsbtnCancel_Click(object sender, EventArgs e)
		{
			this.DialogResult = DialogResult.Cancel;
			this.Close();
		}

		private void btnSelectForm_Click(object sender, EventArgs e)
		{
			FormSelectRepositoryEx frm = new FormSelectRepositoryEx(_service);
			frm.MultiSelect = false;
			frm.AllowChangeDomain = false;
			frm.AllowChangeType = false;
			frm.AllowCreateNewItem = true;
			frm.AllowedTypes = new ItemType[] { ItemType.HumanActivity };
			frm.RepositoryID = Global.Status.CurrentRepositoryId;
			if ( _service != null ) {
				frm.SelectedItem = _service.HumanActivity;
			} else if ( _logact != null ) {
				frm.SelectedItem = _logact.GetHumanActivity();
			}
			if ( frm.ShowDialog() == DialogResult.OK ) {
				Repository.HumanActivity ha = frm.SelectedItem as Repository.HumanActivity;
				if ( _service != null ) {
					_service.HumanActivity = ha;
				} else if ( _logact != null ) {
					_logact.HumanActivityID = ( ha != null ? ha.ID : -1 );
				}
				showHActivityInfo();
			}
		}

		private void btnViewForm_Click(object sender, EventArgs e)
		{

		}

		#endregion

		private void listBox_DrawItem(object sender, DrawItemEventArgs e)
		{
			ListBox lb = sender as ListBox;
			if ( lb == null ) return;
			HumanComponentParticipant part = lb.Items[e.Index] as HumanComponentParticipant;
			if ( part == null ) return;
			int imgindex = getImgIndex(part.Type);
			e.DrawBackground();
			Rectangle rectText = e.Bounds;
			if ( imgindex >= 0 ) {
				e.Graphics.DrawImageUnscaled(imageListParts.Images[imgindex], e.Bounds.X + 1, e.Bounds.Y + 1);
				rectText = new Rectangle(e.Bounds.X + 20, e.Bounds.Y, e.Bounds.Width - 20, e.Bounds.Height);
			}
			using ( SolidBrush foreBrush = new SolidBrush(e.ForeColor) )
			using ( StringFormat sf = new StringFormat(StringFormat.GenericTypographic) ) {
				sf.LineAlignment = StringAlignment.Center;
				sf.Trimming = StringTrimming.EllipsisCharacter;
				e.Graphics.DrawString(part.ToString(), e.Font, foreBrush, rectText, sf);
			}
			if ( ( e.State & DrawItemState.Selected ) == DrawItemState.Selected ) {
				e.DrawFocusRectangle();
			}
		}

		#endregion

	}
}